var AppUtils = require('../utils/AppUtils');
var WSServer = require('./WSServer');
var WSClient = require('./WSClient');
var IPAddress = require('./IPAddress'); // ip地址（ protocal://ip:port）
// var OnlineNodeList = require('./OnlineNodeList'); 
// var WSConnectionList = require('./WSConnectionList');

/**
 * P2P 网络节点
 */
class WSNode {
  constructor(ip, port) {
    this.appUtils = AppUtils.getSingle();

    this.wsIpAddress = new IPAddress(ip,port);
    this.appUtils.wsIpAddress = this.wsIpAddress;

    this.wsServer = WSServer.getSingle(this.wsIpAddress);

    // this.onlineNodeList = new OnlineNodeList();
    // this.clientList = new WSConnectionList();

    // 保存两个用户消息处理事件，给 wsServer 和 wsClient用
    this.userServerOnMsgFunc = null;
    this.userClientOnMsgFunc = null;
  }

  /**
   * 0.1 设置接收消息事件方法 - 提供给p2p模块使用者
   * @param funcServer(msg, connObj, wsServerObj)
   * @param funcClient(msg, connObj, wsServerObj)
   */
  setOnMsgEvent(funcServer,funcClient) { 
    if (this.appUtils.isFunc(funcServer)) {
      this.userServerOnMsgFunc = funcServer;
    } else { 
      throw new Error('funcServer 必须是一个函数');
    }

    if (this.appUtils.isFunc(funcClient)) {
      this.userClientOnMsgFunc = funcClient;
    } else { 
      throw new Error('funcClient 必须是一个函数');
    }

    this.wsServer.setOnMsgEvent(funcServer,funcClient);
  }

  /**
   * 0.2 获取 服务端与 客户端 连接对象 的数量
   */
  getServerConnCount() { 
    return this.wsServer.wssServer.connections.length;
  }

  /**
   * 0.3 获取 服务端与 指定下标客户端 的 连接对象
   * @param {number} index
   */
  getServerConnByIndex(index) { 
    return this.wsServer.wssServer.connections[index];
  }

  /**
   * 1.0 开启节点工作
   */
  startWork() {
    if (this.appUtils.isFunc(this.userClientOnMsgFunc) && this.appUtils.isFunc(this.userServerOnMsgFunc)) {
      this.wsServer.startWSServer();
    } else { 
      throw new Error('未设置用户自定义OnMsg处理函数~！');
    }
  }

  /**
   * 2.0 加入节点网络
   * @param {string} nodeIp 某个在网节点 的 ip
   * @param {string} nodePort 某个在网节点 的 port
   */
  joinNodeNet(nodeIp,nodePort) {
    var client = new WSClient(nodeIp, nodePort);
    client.setOnMsgEvent(this.userClientOnMsgFunc);
    client.connect();
  }

  /**
   * 3.0 广播区块链数据给其它节点
   */
  broadBlockData(data) {
    if (typeof data !== 'string')
      data = JSON.stringify(data);
    
    this.appUtils.logger.logSContent('broadBlockData(data)', '广播了一个最新的区块：', data);
    
    this.wsServer.wssServer.broadcastUTF(data);
  }

  /**
   * 0.0 获取 节点 单例对象
   * @param {string} ip 节点ip
   * @param {string} port 节点内部wsServer端口
   */
  static getSingle(ip, port) { 
    if (!this.onlyNode) {
      if (ip instanceof IPAddress) {
        this.onlyNode = new WSNode(ip.ip, ip.port);
      } else {
        this.onlyNode = new WSNode(ip, port);
      }
    }
    return this.onlyNode;
  }
}

WSNode.onlyNode = null;

module.exports = WSNode;